﻿using System;
using System.Collections.Generic;
using System.ComponentModel;

namespace Toybox.NicoSharp.Live
{
  using Extensions;

  partial class LiveMessageClient : INotifyPropertyChanged
  {
    public class PostLimitter
    {

      #region [INotifyPropertyChanged]

      public event PropertyChangedEventHandler PropertyChanged;

      protected void OnPropertyChanged(string property)
      {
        if (PropertyChanged != null)
          PropertyChanged(this, new PropertyChangedEventArgs(property));
      }

      #endregion [INotifyPropertyChanged]


      #region Constructor

      public PostLimitter()
      {
        this.Enable = false;
        this.Count = 10;
        this.Time = 20;

        this._que = new Queue<int>();
        this._lock = new object();
      }

      #endregion Constructor


      #region Public Members

      /// <summary>
      /// カウントの可否
      /// </summary>
      public bool Enable
      {
        get { return _enable; }
        set
        {
          if (_enable == value) return;

          _enable = value;

          OnPropertyChanged("Enable");
        }
      }
      private bool _enable;

      /// <summary>
      /// 限界数
      /// </summary>
      public int Count
      {
        get { return _count; }
        set
        {
          if (_count == value) return;

          _count = value;

          OnPropertyChanged("Count");
        }
      }
      private int _count;

      /// <summary>
      /// 時間(sec)
      /// </summary>
      public int Time
      {
        get { return _time; }
        set
        {
          if (_time == value) return;

          _time = value;

          OnPropertyChanged("Time");
        }
      }
      private int _time;

      #endregion Public Members

      #region Private Members

      private Queue<int> _que;
      private readonly object _lock;

      #endregion Private Members


      #region Public Methods

      /// <summary>
      /// カウントキューに追加
      /// </summary>
      /// <returns></returns>
      public bool Add()
      {
        lock (_lock)
        {
          if (_que.Count >= Count)
            return false;

          _que.Enqueue(DateTime.UtcNow.GetUnixTime());
        }
        return true;
      }

      /// <summary>
      /// カウントキューをチェック
      /// </summary>
      /// <returns></returns>
      public int Check()
      {
        int time = DateTime.UtcNow.GetUnixTime();

        lock (_lock)
        {
          for (; true; )
          {
            try
            {
              int last = _que.Peek();

              if ((time - last) > Time)
                _que.Dequeue();
              else break;
            }
            catch { break; }
          }

          return _que.Count;
        }
      }

      /// <summary>
      /// カウントキューのクリア
      /// </summary>
      public void Clear()
      {
        lock (_lock)
        {
          _que.Clear();
        }
      }

      #endregion Public Methods

    }
  }
}